#include "PredicateManager.h"
#include "Exception.h"

sPredicateId PredicateManager::newPredicate(string Predicate) {
    uShort size = 2 + Predicate.size() + 1;
    sRow row = claimNewRow(size);
    row.header.bytes[0] = 0xB0;
    int2ToBytes(row.bytes, size - 2);
    strcpy_s(reinterpret_cast<char*>(row.bytes + 2), size - 2, Predicate.c_str());
    row.bytes[size - 1] = 0x0;
    sPredicateId res = row.header.valueId;
    BufferManager::setModified(res.blockId);
    BufferManager::unpinBlock(res.blockId);
    return res;
}

string PredicateManager::getPredicate(sPredicateId sId) {
    sRow row = getRow(sId);
	if ((row.header.bytes[0] & M_1011_x4) != 0xB0)
        throw ERR_NO_PREDICATE_ROW;

    string res = string(reinterpret_cast<char*>(row.bytes + 2));
    BufferManager::unpinBlock(sId.blockId);

    return res;
}

sPredicateId PredicateManager::findPredicate(string predicate) {
    Block* block;
    blockId bId = 0;
    while (bId < DiscManager::getDiscSize()) {
        block = BufferManager::pinBlock(bId);
        if (block->isFree()) {
            bId++;
            break;
        }
        uShort rowCount = block->getRowCount();
        rowId rId = 0;
        while (rId < rowCount) {
            sRow row = block->getRow(rId);
			if ((row.header.bytes[0] & M_1011_x4) == 0xB0) {
                if (strcmp(predicate.c_str(), reinterpret_cast<char*>(row.bytes + 2)) == 0) {
                    BufferManager::unpinBlock(bId);
                    return sPredicateId{ bId, rId };
                }
            }
            rId++;
        }
        BufferManager::unpinBlock(bId);
        bId++;
    }
    throw ERR_PREDICATE_DOES_NOT_EXIST;
}

bool PredicateManager::freePredicate(sPredicateId sId) {
    BufferManager::unpinBlock(sId.blockId);
    return true;
}

sPredicateId PredicateManager::bytesToPredicateId(const byte* bytes) {
    return bytesToValueId(bytes);
}

